/*
 ============================================================================
 Name		: BenchmarkAppUi.cpp
 Author	  : Konstantin Knizhnik
 Copyright   : GigaBASE is freeware
 Description : CBenchmarkAppUi implementation
 ============================================================================
 */

// INCLUDE FILES
#include <avkon.hrh>
#include <aknmessagequerydialog.h>
#include <aknnotewrappers.h>
#include <stringloader.h>
#include <f32file.h>
#include <s32file.h>
#include <hlplch.h>

#include <Benchmark_0xECAA1827.rsg>

#include "Benchmark_0xECAA1827.hlp.hrh"
#include "Benchmark.hrh"
#include "Benchmark.pan"
#include "BenchmarkApplication.h"
#include "BenchmarkAppUi.h"
#include "BenchmarkAppView.h"

#include <gigabase.h>

const int nRecords = 10000;
const int nSequentialSearches = 10;

class Record {
  public:
    char_t const* key;
    char_t const* value;

    TYPE_DESCRIPTOR((KEY(key, INDEXED), FIELD(value)));
};

REGISTER(Record);

// ============================ MEMBER FUNCTIONS ===============================


// -----------------------------------------------------------------------------
// CBenchmarkAppUi::ConstructL()
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CBenchmarkAppUi::ConstructL()
	{
	// Initialise app UI with standard value.
	BaseConstructL(CAknAppUi::EAknEnableSkin);

	// Create view object
	iAppView = CBenchmarkAppView::NewL(ClientRect());

	}
// -----------------------------------------------------------------------------
// CBenchmarkAppUi::CBenchmarkAppUi()
// C++ default constructor can NOT contain any code, that might leave.
// -----------------------------------------------------------------------------
//
CBenchmarkAppUi::CBenchmarkAppUi()
	{
	// No implementation required
	}

// -----------------------------------------------------------------------------
// CBenchmarkAppUi::~CBenchmarkAppUi()
// Destructor.
// -----------------------------------------------------------------------------
//
CBenchmarkAppUi::~CBenchmarkAppUi()
	{
	if (iAppView)
		{
		delete iAppView;
		iAppView = NULL;
		}

	}

// -----------------------------------------------------------------------------
// CBenchmarkAppUi::HandleCommandL()
// Takes care of command handling.
// -----------------------------------------------------------------------------
//
void CBenchmarkAppUi::HandleCommandL(TInt aCommand)
	{
	switch (aCommand)
		{
		case EEikCmdExit:
		case EAknSoftkeyExit:
			Exit();
			break;

		case ECommand2:
			{

			// Load a string from the resource file and display it
			HBufC* textResource = StringLoader::LoadLC(R_COMMAND2_TEXT);
			CAknInformationNote* informationNote;

			informationNote = new (ELeave) CAknInformationNote;

			// Show the information Note with
			// textResource loaded with StringLoader.
			informationNote->ExecuteLD(*textResource);

			// Pop HBuf from CleanUpStack and Destroy it.
			CleanupStack::PopAndDestroy(textResource);
			}
			break;
		case ECommand1:
			{
			    int i, n;
			    char_t buf[32];
			    char result[1024];
			    int pos = 0;
			    dbDatabase db(dbDatabase::dbAllAccess, 16);
			    if (db.open(_T("E:\\benchmark.dbs"))) {
			        dbQuery q;
			        dbCursor<Record> cursor;
			        q = _T("key="),buf;
			        nat8 key = 1999;
			        nat8 sum = 0;
			        time_t start = time(NULL);
			        for (i = 0; i < nRecords; i++) {
			            Record rec;
			            key = (3141592621u*key + 2718281829u) % 1000000007u;
			            sum += key;
			            SPRINTF(SPRINTF_BUFFER(buf), T_INT8_FORMAT _T("."), key);
			            rec.key = buf;
			            rec.value = buf;
			            insert(rec);
			        }
			        db.commit();
			        pos += sprintf(result+pos, "Insert %d records in %d seconds\n", nRecords, int(time(NULL) - start));
			        //printf("Insert %d records in %d seconds\n", nRecords, int(time(NULL) - start)); 

			        start = time(NULL);
			        key = 1999;
			        for (i = 0; i < nRecords; i++) {
			            key = (3141592621u*key + 2718281829u) % 1000000007u;
			            SPRINTF(SPRINTF_BUFFER(buf), T_INT8_FORMAT _T("."), key);
			            n = cursor.select(q);
			            assert(n == 1);
			            assert(STRCMP(cursor->key, buf) == 0);
			        }
			        pos += sprintf(result+pos, "Perform %d index searches in %d seconds\n", nRecords, int(time(NULL) - start));			        
			        //printf("Perform %d index searches in %d seconds\n", nRecords, int(time(NULL) - start)); 
			        			        
			        q = _T("value=key");
			        start = time(NULL);
			        for (i = 0; i < nSequentialSearches; i++) {
			            n = cursor.select(q);
			            assert(n == nRecords);
			            do {
			                n -= 1;
			            } while (cursor.next());
			            assert(n == 0);
			        }
			        pos += sprintf(result+pos, "Perform sequential search through %d records in %d seconds\n", nRecords, int(time(NULL) - start));
			        //printf("Perform sequential search through %d records in %d seconds\n", nRecords, int(time(NULL) - start)); 

			        q = _T("value=key order by value");
			        start = time(NULL);
			        n = cursor.select(q, dbCursorForUpdate);
			        assert(n == nRecords);
			        pos += sprintf(result+pos, "Perform sequential search with sorting %d records in %d seconds\n", nRecords, int(time(NULL) - start));
			        //printf("Perform sequential search with sorting %d records in %d seconds\n", nRecords, int(time(NULL) - start)); 
		        
			        start = time(NULL);
			        cursor.removeAll();
			        pos += sprintf(result+pos, "Remove %d records in %d seconds\n", nRecords, int(time(NULL) - start));
			        //printf("Remove %d records in %d seconds\n", nRecords, int(time(NULL) - start));
			        db.close();
			    } else {
					pos = sprintf(result, "Failed to open database file");
			    }
				wchar_t* wcsbuf = new wchar_t[pos+1];
				mbstowcs(wcsbuf, result, pos+1);
				CAknMessageQueryDialog* dlg = new (ELeave) CAknMessageQueryDialog();
				dlg->PrepareLC(R_BENCHMARK_RESULT_DIALOG);
				HBufC* title = iEikonEnv->AllocReadResourceLC(R_BENCHMARK_RESULT_DIALOG_TITLE);
				dlg->QueryHeading()->SetTextL(*title);
				CleanupStack::PopAndDestroy(); //title
				dlg->SetMessageTextL(TPtrC((TUint16*)wcsbuf, pos));
				dlg->RunLD();
			}
			break;
		case EHelp:
			{

			CArrayFix<TCoeHelpContext>* buf = CCoeAppUi::AppHelpContextL();
			HlpLauncher::LaunchHelpApplicationL(iEikonEnv->WsSession(), buf);
			}
			break;
		case EAbout:
			{

			CAknMessageQueryDialog* dlg = new (ELeave) CAknMessageQueryDialog();
			dlg->PrepareLC(R_ABOUT_QUERY_DIALOG);
			HBufC* title = iEikonEnv->AllocReadResourceLC(R_ABOUT_DIALOG_TITLE);
			dlg->QueryHeading()->SetTextL(*title);
			CleanupStack::PopAndDestroy(); //title
			HBufC* msg = iEikonEnv->AllocReadResourceLC(R_ABOUT_DIALOG_TEXT);
			dlg->SetMessageTextL(*msg);
			CleanupStack::PopAndDestroy(); //msg
			dlg->RunLD();
			}
			break;
		default:
			Panic(EBenchmarkUi);
			break;
		}
	}
// -----------------------------------------------------------------------------
//  Called by the framework when the application status pane
//  size is changed.  Passes the new client rectangle to the
//  AppView
// -----------------------------------------------------------------------------
//
void CBenchmarkAppUi::HandleStatusPaneSizeChange()
	{
	iAppView->SetRect(ClientRect());
	}

CArrayFix<TCoeHelpContext>* CBenchmarkAppUi::HelpContextL() const
	{
#warning "Please see comment about help and UID3..."
	// Note: Help will not work if the application uid3 is not in the
	// protected range.  The default uid3 range for projects created
	// from this template (0xE0000000 - 0xEFFFFFFF) are not in the protected range so that they
	// can be self signed and installed on the device during testing.
	// Once you get your official uid3 from Symbian Ltd. and find/replace
	// all occurrences of uid3 in your project, the context help will
	// work. Alternatively, a patch now exists for the versions of 
	// HTML help compiler in SDKs and can be found here along with an FAQ:
	// http://www3.symbian.com/faq.nsf/AllByDate/E9DF3257FD565A658025733900805EA2?OpenDocument
	CArrayFixFlat<TCoeHelpContext>* array = new (ELeave) CArrayFixFlat<
			TCoeHelpContext> (1);
	CleanupStack::PushL(array);
	array->AppendL(TCoeHelpContext(KUidBenchmarkApp, KGeneral_Information));
	CleanupStack::Pop(array);
	return array;
	}

// End of File
